/**
 * i18n语法检查工具
 * 检查语言文件中的语法错误并提供详细报告
 */
import i18n, { getSupportedLocales } from './i18n';

// 定义错误类型
interface SyntaxError {
  locale: string;
  key: string;
  value: string;
  reason: string;
}

// 存储全局错误报告
let lastErrors: SyntaxError[] = [];

/**
 * 工具函数：检查字符串中的大括号是否配对
 */
function checkBracePairs(value: string): boolean {
  // 特殊处理空字符串或非字符串
  if (!value || typeof value !== 'string') return true;

  // 移除转义的大括号，避免误判
  const cleanValue = value
    .replace(/\\{/g, '')
    .replace(/\\}/g, '');

  const openCount = (cleanValue.match(/{/g) || []).length;
  const closeCount = (cleanValue.match(/}/g) || []).length;

  return openCount === closeCount;
}

/**
 * 展平嵌套对象，便于检查所有字符串
 */
function flattenObj(obj: any, prefix = ''): Record<string, string> {
  return Object.keys(obj).reduce((acc, key) => {
    const prefixedKey = prefix ? `${prefix}.${key}` : key;
    if (typeof obj[key] === 'object' && obj[key] !== null) {
      Object.assign(acc, flattenObj(obj[key], prefixedKey));
    } else {
      acc[prefixedKey] = obj[key];
    }
    return acc;
  }, {} as Record<string, string>);
}

/**
 * 检查语言文件是否正确导入
 */
function checkLocalesLoaded() {
  const supportedLocales = getSupportedLocales();
  const availableLocales = i18n.global.availableLocales;

  // 检查是否所有支持的语言都已加载
  const missingLocales = supportedLocales.filter(
    locale => !Array.from(availableLocales).includes(locale)
  );

  if (missingLocales.length > 0) {
    console.warn(`[i18n] 以下语言未正确加载: ${missingLocales.join(', ')}`);
    return false;
  }

  return true;
}

/**
 * 主要检查函数：检查所有语言文件中的语法错误
 */
export function checkI18nSyntax() {
  console.log('[i18n] 开始检查语言文件语法...');
  lastErrors = [];

  try {
    // 首先检查语言文件是否都加载了
    if (!checkLocalesLoaded()) {
      console.error('[i18n] 语言文件加载不完整，请检查导入');
      return false;
    }

    // 获取所有支持的语言
    const locales = getSupportedLocales();
    const messages = i18n.global.messages.value;

    // 逐个检查每种语言
    locales.forEach(locale => {
      const localeKey = locale as keyof typeof messages;
      const localeMessages = messages[localeKey];

      if (!localeMessages) {
        console.warn(`[i18n] 语言 "${locale}" 的消息为空`);
        return;
      }

      // 扁平化处理便于检查所有字符串
      const flattenedMessages = flattenObj(localeMessages);

      // 检查每个翻译字符串
      Object.entries(flattenedMessages).forEach(([key, value]) => {
        // 跳过非字符串值
        if (typeof value !== 'string') return;

        // 检查大括号配对
        if (!checkBracePairs(value)) {
          lastErrors.push({
            locale,
            key,
            value,
            reason: '大括号不配对'
          });
        }

        // 检查其他可能的语法错误，如HTML标签未闭合等
        // 这里可以添加更多的检查逻辑
      });
    });

    // 报告检查结果
    if (lastErrors.length > 0) {
      console.error(`[i18n] 发现 ${lastErrors.length} 个语法错误:`);
      lastErrors.forEach(err => {
        console.error(`  - [${err.locale}] ${err.key}: "${err.value}" (${err.reason})`);
      });

      // 提供错误修复建议
      console.warn('[i18n] 这是一个语法错误,请检查语言文件格式是否正确');
      console.warn('[i18n] 错误代码26通常表示插值语法错误,例如 {name} 格式错误或大括号不匹配');
      console.warn('[i18n] 建议方案: 检查语言文件中的大括号是否成对出现，特殊字符是否需要转义');

      return false;
    }

    console.log('[i18n] 语法检查完成，未发现错误');
    return true;
  } catch (error) {
    console.error('[i18n] 检查语言文件语法时出错:', error);
    console.warn('[i18n] 这是一个语法错误,请检查语言文件格式是否正确');
    console.warn('[i18n] 错误代码26通常表示插值语法错误,例如 {name} 格式错误或大括号不匹配');
    return false;
  }
}

/**
 * 获取最近的语法错误报告
 */
export function getLastSyntaxErrors() {
  return lastErrors;
}

/**
 * 尝试识别和修复常见语法错误
 */
export function tryFixSyntaxErrors() {
  if (lastErrors.length === 0) {
    console.log('[i18n] 没有需要修复的错误');
    return null;
  }

  const fixes: Record<string, Record<string, string>> = {};

  lastErrors.forEach(error => {
    if (!fixes[error.locale]) {
      fixes[error.locale] = {};
    }

    // 尝试自动修复大括号不配对问题
    if (error.reason === '大括号不配对') {
      const openCount = (error.value.match(/{/g) || []).length;
      const closeCount = (error.value.match(/}/g) || []).length;

      let fixedValue = error.value;

      if (openCount > closeCount) {
        // 添加缺失的闭合括号
        for (let i = 0; i < openCount - closeCount; i++) {
          fixedValue += '}';
        }
      } else if (closeCount > openCount) {
        // 移除多余的闭合括号
        for (let i = 0; i < closeCount - openCount; i++) {
          fixedValue = fixedValue.replace(/}([^{]*$)/, '$1');
        }
      }

      fixes[error.locale][error.key] = fixedValue;
    }
  });

  return fixes;
}

export default {
  checkI18nSyntax,
  getLastSyntaxErrors,
  tryFixSyntaxErrors
}; 